package com.ten.java.jarupdate.util;

import lombok.Cleanup;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.Arrays;

/**
 * IO工具类
 * @author zhangxs
 * @date 2022/5/7 15:47
 */
@Slf4j
public class IOUtils {

    private IOUtils() {}

    /**
     * 默认缓存大小5M
     */
    private static final int DEFAULT_BUFFER_SIZE = 1024 * 1024 * 5;

    /**
     * 默认编码格式
     */
    private static final String DEFAULT_CHARSET_NAME = "UTF-8";

    /**
     * 读取file里的内容
     * @param file
     * @return String
     * @author zhangxs
     * @date 2022/6/9 9:56
     */
    public static String read(File file) {
        try {
            @Cleanup
            FileReader fileReader = new FileReader(file);
            return read(fileReader);
        } catch (Exception e) {
            log.error("读取文件异常:", e);
            return null;
        }
    }

    /**
     * 读取reader里的内容
     * @param reader
     * @return String
     * @author zhangxs
     * @date 2022/6/9 9:56
     */
    public static String read(Reader reader) {
        final char[] chars = new char[1024];
        StringBuilder stringBuilder = new StringBuilder();
        try {
            int count = reader.read(chars);
            while (count != -1) {
                stringBuilder.append(chars, 0, count);
                count = reader.read(chars);
            }
            return stringBuilder.toString();
        } catch (IOException e) {
            log.error("读取异常：", e);
            return null;
        }
    }

    /**
     * 写入字符串到文件
     * @param str 要写入的字符串
     * @param file 要写入到的文件
     * @return void
     * @author zhangxs
     * @date 2022/7/11 15:41
     */
    public static void write(String str, File file) {
        write(str, file, DEFAULT_CHARSET_NAME);
    }

    /**
     * 写入字符串到文件
     * @param str 要写入的字符串
     * @param file 要写入到的文件
     * @param charset 编码格式
     * @return void
     * @author zhangxs
     * @date 2022/7/11 15:41
     */
    public static void write(String str, File file, String charset) {
        try {
            @Cleanup
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            output(str, fileOutputStream, charset);
        } catch (Exception e) {
            log.error("输出异常：", e);
        }
    }

    /**
     * 输出字符串到输出流（默认使用IOUtils.DEFAULT_CHARSET_NAME字段的编码格式）
     * @param string
     * @param outputStream
     * @return void
     * @author zhangxs
     * @date 2022/6/9 9:56
     */
    public static void output(String string, OutputStream outputStream) {
        output(string, outputStream, DEFAULT_CHARSET_NAME);
    }

    /**
     * 输出字符串到输出流
     * @param string
     * @param outputStream
     * @param charset 编码格式
     * @return void
     * @author zhangxs
     * @date 2022/6/9 9:56
     */
    public static void output(String string, OutputStream outputStream, String charset) {
        try {
            @Cleanup
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(string.getBytes(charset));
            copy(byteArrayInputStream, outputStream);
        } catch (Exception e) {
            log.error("输出异常：", e);
        }
    }

    /**
     * 读取字节流的数据到文件
     * @param inputStream
     * @param file
     * @return void
     * @author zhangxs
     * @date 2022/6/9 9:57
     */
    public static void toFile(@NonNull InputStream inputStream, @NonNull File file) {
        try {
            @Cleanup
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            copy(inputStream, fileOutputStream);
        } catch (IOException ioException) {
            log.error("复制输入流数据到文件异常：", ioException);
        }
    }

    public static void copy(File source, File target) {
        try {
            copy(new FileInputStream(source), new FileOutputStream(target));
        } catch (FileNotFoundException e) {
            log.error("复制文件异常：", e);
        }
    }

    /**
     * 拷贝数据
     * @param inputStream
     * @param outputStream
     * @return void
     * @author zhangxs
     * @date 2022/6/9 9:57
     */
    public static void copy(@NonNull InputStream inputStream, @NonNull OutputStream outputStream) {
        try {
            @Cleanup
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            @Cleanup
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
            int count = bufferedInputStream.read(buffer);
            while (count != -1) {
                bufferedOutputStream.write(buffer, 0, count);
                outputStream.flush();
                count = bufferedInputStream.read(buffer);
            }
        } catch (IOException ioException) {
            log.error("复制输入流数据到输出流异常：", ioException);
        }
    }

    /**
     * 关闭流
     * @param closeables
     * @return void
     * @author zhangxs
     * @date 2022/6/9 9:57
     */
    public static void close(Closeable... closeables) {
        Arrays.stream(closeables).forEach(IOUtils::close);
    }

    /**
     * 关闭流
     * @param closeable
     * @return void
     * @author zhangxs
     * @date 2022/6/9 9:57
     */
    public static void close(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (IOException e) {
            log.error("关闭流异常", e);
        }
    }
}